package com.centerm.bluetooth.common.controller;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager;

import com.alibaba.fastjson.JSONObject;
import com.centerm.bluetooth.common.Command;
import com.centerm.bluetooth.common.listener.IPBOCListener;
import com.centerm.bluetooth.core.controller.BaseController;
import com.centerm.bluetooth.core.controller.constants.Constants;
import com.centerm.bluetooth.core.controller.constants.WaitEnum;
import com.centerm.bluetooth.ibridge.BluetoothIBridgeDevice;
import com.centerm.bluetooth.model.Respond;
import com.centerm.bluetooth.receive.CMDParseReceiver;
import com.centerm.util.HexUtil;
import com.centerm.util.TlvUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by linwenhui on 2017/4/28.
 */

public class PBOCController extends BaseController<IPBOCListener> {
    private final static int PBOC = 0x01;
    private final static int END = 0x02;
    private final static int READ_PBOC_RESULT = 0x03;
    private final static int QPBOC = 0x04;
    private final static int READ_QPBOC_RESULT = 0x05;
    private int type;

    public PBOCController(@NonNull Context context) {
        super((byte) 0x05, context);
    }

    protected byte[] buildPBOCReqDatas(String money) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("9F02", money);// 授权金额
        map.put("9F03", "000000000000");// 其他金额
        map.put("9C", "00");// 交易类型
        map.put("DF7C", "01");//自定义交易类型
        map.put("DF71", "06");//PBOC交易流程
        map.put("DF72", "01");// 是否强制联机：
        map.put("DF73", "00");//账户选择标识
        return TlvUtil.mapToTlv(map);
    }

    public boolean startPBOC(String money) throws IOException {
        if (wait == WaitEnum.FREE || wait == WaitEnum.WAIT_SWIPER_COMPELETE) {
            final byte[] tlvData = buildPBOCReqDatas(money);
            type = PBOC;
            boolean reslut = send(Command.PBOC, tlvData);
            if (reslut) {
                LocalBroadcastManager.getInstance(context).registerReceiver(new PBOCResultReceiver(), new IntentFilter(Constants.CMD_ACTION + "0504"));
                setTimeoutTimer();
            }
            return reslut;
        }
        return false;
    }

    public boolean startQPBOC(String money) throws IOException {
        if (wait == WaitEnum.FREE || wait == WaitEnum.WAIT_SWIPER_COMPELETE) {
            final byte[] tlvData = buildPBOCReqDatas(money);
            type = QPBOC;
            boolean reslut = send(Command.QPBOC, tlvData);
            if (reslut) {
                LocalBroadcastManager.getInstance(context).registerReceiver(new QPBOCResultReceiver(), new IntentFilter(Constants.CMD_ACTION + "050F"));
                setTimeoutTimer();
            }
            return reslut;
        }
        return false;
    }

    public boolean readPBOCResult() throws IOException {
        if (wait == WaitEnum.FREE) {
            type = READ_PBOC_RESULT;
            boolean res = send(Command.PBOC_RESULT, null);
            if (res) {
                setTimeoutTimer();
            }
            return res;
        }
        return false;
    }

    public void endPBOC(@IntRange(from = 0, to = 1) int flag) throws IOException {
        type = END;
        boolean res = send(Command.END_PBOC, new byte[]{(byte) flag});
        if (res)
            setTimeoutTimer();
    }

    public boolean readQPBOCResult() throws IOException {
        if (wait == WaitEnum.FREE) {
            type = READ_QPBOC_RESULT;
            boolean res = send(Command.QPBOC_RESULT, null);
            if (res)
                setTimeoutTimer();
            return res;
        }
        return false;
    }

    @Override
    public void onDataReceived(BluetoothIBridgeDevice device, Respond respond) {
        super.onDataReceived(device, respond);
        switch (type) {
            case PBOC:
                if (baseListener != null)
                    baseListener.onWaitForPBOCResult();
                break;
            case READ_PBOC_RESULT:
            case READ_QPBOC_RESULT:
                parsePBOCResult(respond.getContent());
                break;
            case END:
                if (baseListener != null)
                    baseListener.onEndPBOC();
                break;
        }
    }

    protected void parsePBOCResult(byte[] params) {
        if (params[0] == 0 || params[0] == 0x03) {
            JSONObject resultObj = new JSONObject();
            //随机数
            byte[] randomBytes = new byte[8];
            System.arraycopy(params, 1, randomBytes, 0, 8);
            resultObj.put("random", HexUtil.byte2HexStr(randomBytes));

            //卡片序列号
            byte[] cardSerialBytes = new byte[3];
            System.arraycopy(params, 9, cardSerialBytes, 0, 3);
            resultObj.put("cardSerial", HexUtil.toASCII(cardSerialBytes));

            //卡有效期
            byte[] expireDateBytes = new byte[4];
            System.arraycopy(params, 12, expireDateBytes, 0, 4);
            resultObj.put("expireDate", HexUtil.toASCII(expireDateBytes));

            //卡号明文长度
            int panLen = params[16];

            //卡号明文数据
            byte[] panBytes = new byte[10];
            System.arraycopy(params, 17, panBytes, 0, 10);
            resultObj.put("pan", HexUtil.byte2HexStr(panBytes).replace("F", "").replace("f", ""));

            //卡号密文长度
            int panSecureLen = params[27];

            //卡号密文数据
            byte[] panSecureBytes = new byte[panSecureLen];
            System.arraycopy(params, 28, panSecureBytes, 0, panSecureLen);
            resultObj.put("securePan", HexUtil.byte2HexStr(panSecureBytes));

            //IC卡数据密文长度
            byte[] icLenByte = new byte[2];
            System.arraycopy(params, 28 + panSecureLen, icLenByte, 0, 2);
            int icLen = 0;
            try {
                icLen = Integer.valueOf(HexUtil.byte2HexStr(icLenByte), 16);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }

            //IC卡数据密文信息
            if (icLen > 0) {
                byte[] icDataBytes = new byte[icLen];
                System.arraycopy(params, 30 + panSecureLen, icDataBytes, 0, icLen);
                resultObj.put("icdata", HexUtil.byte2HexStr(icDataBytes));
            } else {
                resultObj.put("icdata", "");
            }
            if (baseListener != null) {
                baseListener.onPBOCResult(resultObj.toJSONString());
            }


        } else {
            try {
                endPBOC(1);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private class PBOCResultReceiver extends CMDParseReceiver {

        @Override
        public void onReceive(Context context, Intent intent, byte[] params, int paramLen) {
            if (paramLen > 0) {
                if (params[0] == 0x00) {
                    try {
                        readPBOCResult();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        endPBOC(1);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                try {
                    endPBOC(1);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private class QPBOCResultReceiver extends CMDParseReceiver {

        @Override
        public void onReceive(Context context, Intent intent, byte[] params, int paramLen) {
            if (paramLen > 0) {
                if (params[0] == 0x00) {
                    try {
                        readQPBOCResult();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    if (baseListener != null)
                        baseListener.onPBOCError();
                    try {
                        endPBOC(1);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            } else {
                if (baseListener != null)
                    baseListener.onPBOCError();
                try {
                    endPBOC(1);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
